package com.dongnao.network.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

/**
 * 测试与 tomcat 建立连接
 *
 * @author sjy
 * @date 2024年06月28日 16:30
 */
public class SocketChannelTest implements Runnable {

    Selector selector;

    public SocketChannelTest()  {
        try {
            selector = Selector.open();
            new Thread(this).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SocketChannelTest test = new SocketChannelTest();
        LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
        test.call();
    }

    private void call() {
        while (true) {
            System.out.println("====时间：" + System.currentTimeMillis());
            SocketChannel channel = null;

            try {
                channel = SocketChannel.open();
                channel.configureBlocking(false);
                channel.socket().setSoLinger(false, -1);
                channel.socket().setReuseAddress(true);
                channel.socket().setKeepAlive(true);
                channel.socket().setTcpNoDelay(true);
                channel.connect(new InetSocketAddress("localhost", 9090));

                SelectionKey key = channel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ);
            } catch (Exception e) {
                e.printStackTrace();
                if (channel != null) {
                    try {
                        channel.close();
                    } catch (Exception ignore) {
                    }
                }
            } finally {
                LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
            }
        }
    }

    @Override
    public void run() {
        while (true) {
            try {
                //非阻塞
                int readyCount = selector.selectNow();
                if (readyCount <= 0) {
                    continue;
                }

                Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
                while (iter.hasNext()) {
                    SelectionKey key = iter.next();
                    iter.remove();

                    SocketChannel channel = (SocketChannel) key.channel();
                    try {
                        //key对应的channel的连接是否已经建立，已准备好的事件是否是可读事件
                        if (key.isValid() && key.isConnectable()) {
                            boolean isConnected = channel.finishConnect();
                            System.out.println("====isConnected: " + isConnected);
                        }

                        if (key.isValid() && key.isReadable()) {
                            System.out.println("====可读事件");
                            ByteBuffer buffer = ByteBuffer.allocate(128);
                            if (channel.read(buffer) == -1) {
                                key.cancel();
                                key.channel().close();
                            }
                        }
                    } catch (Exception e1) {
                        e1.printStackTrace();
                        try {
                            key.cancel();
                            key.channel().close();
                        } catch (Exception e2) {
                            e2.printStackTrace();
                        }
                    }
                }
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }
}
